home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / fixes / fix020 / libray / libobj / flame.c next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  6.5 KB  |  290 lines

  1. /*
  2.  * flame.c
  3.  *
  4.  * Projektarbeit '94
  5.  *
  6.  * written by Reto Mani
  7.  *
  8.  */
  9.  
  10. #include "geom.h"                 /* Definition of Vector, ... */
  11. #include "../libsurf/surface.h"   /* Definition of SurfaceCreate() */
  12. #include "../libtext/texture.h"   /* Definition of Chaos() */
  13. #include "flame.h"                /* Definition of Flame functions */
  14. #include "../liblight/light.h"    /* Definition of LightCreate()
  15. #include "../liblight/point.h"    /* Definition of LightPointCreate() */
  16.  
  17. #define FLAMERATIO   0.2   /* Flamelength/Flamewidth */
  18. /*#define SPEED 5.0 */ /* movement speed of flame */
  19.  
  20. static Methods *iFlameMethods = NULL;
  21. static char flameName[] = "flame";
  22.  
  23. unsigned long FlameTests=0, FlameHits=0;
  24.  
  25.  
  26. /* Create & return reference to a flame */
  27. Geom *FlameCreate(size,pos,lightswitch,speed)   /* Create a Geom Object! */
  28. Float  size,speed;
  29. Vector *pos;
  30. int lightswitch;
  31. {
  32.    Geom    *nob;
  33.    Surface *nsurf;
  34.    Float   delta;
  35.    Vector  vec;
  36.    Color   col;
  37.    Light   *ltmp;
  38.  
  39.    nsurf=SurfaceCreate();
  40.    nsurf->noshadow=TRUE;
  41.  
  42.    nob=GeomCreate((GeomRef)FlameObjCreate(size,pos,speed,nsurf),FlameMethods());
  43.    nob->surf=nsurf;
  44.  
  45.    if (lightswitch)
  46.       {
  47.       /* Create the lights */
  48.       col.r=.8;col.g=.7;col.b=.5;
  49.       delta=size*FLAMERATIO;
  50.       vec.x=pos->x+delta;
  51.       vec.y=pos->y+delta;
  52.       vec.z=pos->z+size/2;
  53.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  54.       LightAddToDefined(ltmp);
  55.       vec.x=pos->x-delta;
  56.       vec.y=pos->y-delta;
  57.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  58.       LightAddToDefined(ltmp);
  59.       vec.x=pos->x+delta;
  60.       vec.y=pos->y-delta;
  61.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  62.       LightAddToDefined(ltmp);
  63.       vec.x=pos->x-delta;
  64.       vec.y=pos->y+delta;
  65.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  66.       LightAddToDefined(ltmp);
  67.       }
  68.  
  69.    NoiseInit();
  70.  
  71.    return nob;
  72. }
  73.  
  74.  
  75. Flame *FlameObjCreate(size,pos,speed,newsurf)  /* Create the Flame Object */
  76. Float    size,speed;
  77. Vector   *pos;
  78. Surface  *newsurf;
  79. {
  80.    Flame *flame;
  81.  
  82.    if (fabs(size)<EPSILON)
  83.       {
  84.       RLerror(RL_WARN,"Degenerate flame.\n");
  85.       return (Flame *)NULL;
  86.       }
  87.  
  88.    flame = (Flame *)share_malloc(sizeof(Flame));
  89.  
  90.    flame->size    = size;
  91.    flame->x       = pos->x;
  92.    flame->y       = pos->y;
  93.    flame->z       = pos->z;
  94.    flame->surface = newsurf;
  95.    flame->speed   = speed;
  96.  
  97.    return flame;
  98. }
  99.  
  100.  
  101. Methods *FlameMethods()
  102. {
  103.    if (iFlameMethods == (Methods *)NULL)
  104.       {
  105.       iFlameMethods = MethodsCreate();
  106.       iFlameMethods->create = (GeomCreateFunc *)FlameObjCreate;
  107.       iFlameMethods->methods = FlameMethods;
  108.       iFlameMethods->name = FlameName;
  109.       iFlameMethods->intersect = FlameIntersect;
  110.       iFlameMethods->normal = FlameNormal;
  111.       iFlameMethods->uv = FlameUV;
  112.       iFlameMethods->enter = FlameEnter;
  113.       iFlameMethods->bounds = FlameBounds;
  114.       iFlameMethods->stats = FlameStats;
  115.       iFlameMethods->checkbounds = TRUE;
  116.       iFlameMethods->closed = TRUE;
  117.       }
  118.    return iFlameMethods;
  119. }
  120.  
  121.  
  122. /* Ray/Flame intersection test */
  123. int FlameIntersect(flame, ray, mindist, maxdist)
  124. Flame *flame;
  125. Ray *ray;
  126. Float mindist, *maxdist;
  127. {
  128.    Float xadj,yadj,zadj,lambda;
  129.    Float u,v;  /* Coord in Flameplane */
  130.    Color color;
  131.  
  132.    FlameTests++;
  133.  
  134.    xadj=ray->pos.x - flame->x;
  135.    yadj=ray->pos.y - flame->y;
  136.    zadj=ray->pos.z - flame->z;
  137.  
  138.    /* calculate coordinates of ray in the flame plane */
  139.    lambda=-xadj*ray->dir.x-yadj*ray->dir.y;
  140.    lambda/=ray->dir.x*ray->dir.x+ray->dir.y*ray->dir.y;
  141.    u=xadj+lambda*ray->dir.x;
  142.    v=yadj+lambda*ray->dir.y;
  143.    if (u<0.0)
  144.       u=-sqrt(u*u+v*v);
  145.    else
  146.       u=sqrt(u*u+v*v);
  147.    v=zadj+lambda*ray->dir.z;
  148.  
  149.    if (v<0.0) 
  150.       return FALSE;
  151.  
  152.    if (FlameCalcColor(flame,u,v,ray->time))
  153.       if (lambda > mindist && lambda < *maxdist)
  154.          {
  155.          *maxdist=lambda;
  156.          FlameHits++;
  157.          return TRUE;
  158.          }
  159.    return FALSE;
  160. }
  161.  
  162.  
  163. /* set the color of the flame depending on coordinates and time */
  164. int FlameCalcColor(flame,u,v,ftime)
  165. Flame *flame;
  166. Float u,v,ftime;
  167. {
  168.    Float rad,uf,vf,chval,turb,tmpv,speed;
  169.    Vector vec;
  170.    Color color;
  171.    
  172.    /* calculate the radius of point (u,v) on the flame */
  173.  
  174.  
  175.    vf=flame->size*flame->size;
  176.    uf=vf*FLAMERATIO*FLAMERATIO;
  177.    vf*=0.25;
  178.    tmpv=v-flame->size*0.5;
  179.    rad=u*u/uf+tmpv*tmpv/vf;
  180.  
  181.    if (rad<1.0)
  182.       {
  183.       /* This is the color-function */
  184.       color.r=(rad < 0.333) ? 1.0 : 1.33-rad;
  185.       color.g=1.0-0.9*rad;
  186.       color.b=(rad < 0.666) ? 1.0-rad*1.5 : 0.0;
  187.  
  188.       /* adding turbulence */
  189.       speed=flame->speed*10.0;
  190.       vec.x=flame->x+u;
  191.       vec.y=flame->y+v-ftime/speed;  /* motion in vertical direction! */
  192.       vec.z=flame->z+ftime/speed;
  193.       chval = Chaos(&vec,4);         /* calling the turbulence function */
  194.       turb=(3.0*v/flame->size)*(chval-.5);
  195.       color.r+=turb;
  196.       color.g+=turb;
  197.       color.b+=turb;
  198.  
  199.       if (color.r<0.0) color.r=0.0; else if (color.r>1.0) color.r=1.0;
  200.       if (color.g<0.0) color.g=0.0; else if (color.g>1.0) color.g=1.0;
  201.       if (color.b<0.0) color.b=0.0; else if (color.b>1.0) color.b=1.0;
  202.  
  203.       if (color.r==0.0 && color.g==0.0 && color.b==0.0) return FALSE;
  204.  
  205.       /* setting the color */
  206.       flame->surface->amb.r=color.r;
  207.       flame->surface->amb.g=color.g;
  208.       flame->surface->amb.b=color.b;
  209.  
  210.       flame->surface->diff.r=color.r;
  211.       flame->surface->diff.g=color.g;
  212.       flame->surface->diff.b=color.b;
  213.  
  214.       return TRUE;
  215.       }
  216.    else
  217.       return FALSE;
  218. }
  219.  
  220.  
  221. /* Compute normal to flame at pos */
  222. int FlameNormal(flame, pos, nrm, gnrm)
  223. Flame *flame;
  224. Vector *pos, *nrm, *gnrm;
  225. {
  226.    nrm->x=(pos->x - flame->x);
  227.    nrm->y=(pos->y - flame->y);
  228.    nrm->z=0.0;
  229.    (void)VecNormalize(nrm);
  230.    *gnrm=*nrm;
  231.    return FALSE;
  232. }
  233.  
  234.  
  235. /* Determine if ray enters (TRUE) or leaves (FALSE) flame at pos */
  236. int FlameEnter(flame, ray, mind, hitd)
  237. Flame *flame;
  238. Ray *ray;
  239. Float mind, hitd;
  240. {
  241.    return TRUE;
  242. }
  243.  
  244.  
  245. /* ARGSUSED */
  246. void FlameUV(flame, pos, norm, uv, dpdu, dpdv)
  247. Flame *flame;
  248. Vector *pos, *norm, *dpdu, *dpdv;
  249. Vec2d *uv;
  250. {
  251. }
  252.  
  253.  
  254. void FlameBounds(flame, bounds)
  255. Flame *flame;
  256. Float bounds[2][3];
  257. {
  258.    Float  diff=flame->size * FLAMERATIO;
  259.  
  260.    bounds[LOW][X]  = flame->x-diff;
  261.    bounds[HIGH][X] = flame->x+diff;
  262.    bounds[LOW][Y]  = flame->y-diff;
  263.    bounds[HIGH][Y] = flame->y+diff;
  264.    bounds[LOW][Z]  = flame->z;
  265.    bounds[HIGH][Z] = flame->z+flame->size;
  266. }
  267.  
  268.  
  269. char *FlameName()
  270. {
  271.    return flameName;
  272. }
  273.  
  274.  
  275. void FlameStats(tests, hits)
  276. unsigned long *tests, *hits;
  277. {
  278.    *tests = FlameTests;
  279.    *hits = FlameHits;
  280. }
  281.  
  282.  
  283. void FlameMethodRegister(meth)
  284. UserMethodType meth;
  285. {
  286.    if (iFlameMethods)
  287.       iFlameMethods->user = meth;
  288. }
  289.  
  290.